import sys
import sqlite3
from datetime import datetime, timezone
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QFont, QPalette, QColor, QIcon

# 配置参数
STYLES = {
    "primary_color": "#2c3e50",
    "secondary_color": "#3498db",
    "font_sizes": {
        "title": 18,
        "content": 14,
        "default": 12
    }
}

class DatabaseManager:
    def __init__(self, db_name='cards.db'):
        self.conn = sqlite3.connect(db_name)
        self._initialize_database()

    def _initialize_database(self):
        with self.conn:
            self.conn.executescript('''
                CREATE TABLE IF NOT EXISTS cards (
                    id INTEGER PRIMARY KEY,
                    question TEXT NOT NULL,
                    answer TEXT NOT NULL,
                    proficiency INTEGER DEFAULT 0,
                    modified DATETIME DEFAULT CURRENT_TIMESTAMP
                );
                
                CREATE TABLE IF NOT EXISTS tags (
                    id INTEGER PRIMARY KEY,
                    name TEXT UNIQUE NOT NULL
                );
                
                CREATE TABLE IF NOT EXISTS card_tags (
                    card_id INTEGER NOT NULL,
                    tag_id INTEGER NOT NULL,
                    FOREIGN KEY(card_id) REFERENCES cards(id) ON DELETE CASCADE,
                    FOREIGN KEY(tag_id) REFERENCES tags(id) ON DELETE CASCADE,
                    UNIQUE(card_id, tag_id)
                );
            ''')

    def execute_query(self, query, params=()):
        cursor = self.conn.cursor()
        cursor.execute(query, params)
        return cursor

    def commit(self):
        self.conn.commit()

    def close(self):
        self.conn.close()

class MemoryApp(QMainWindow):
    data_updated = pyqtSignal()

    def __init__(self):
        super().__init__()
        self.db = DatabaseManager()
        self._init_ui()
        self._load_cards()
        self._setup_shortcuts()

    def _init_ui(self):
        self.setWindowTitle('智能记忆系统')
        self.resize(1000, 700)
        self._create_central_widget()
        self._create_menu()

    def _create_central_widget(self):
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QHBoxLayout(central_widget)

        # 卡片列表
        self.card_list = QListWidget()
        self.card_list.setFont(QFont('微软雅黑', STYLES['font_sizes']['content']))
        self.card_list.itemDoubleClicked.connect(self._show_card_detail)
        layout.addWidget(self.card_list, 3)

        # 右侧面板
        right_panel = QVBoxLayout()
        
        # 信息显示
        self.info_label = QLabel()
        self.info_label.setFont(QFont('微软雅黑', STYLES['font_sizes']['default']))
        right_panel.addWidget(self.info_label)

        # 问题显示
        self.question_display = QTextEdit()
        self.question_display.setReadOnly(True)
        self.question_display.setFont(QFont('微软雅黑', STYLES['font_sizes']['content']))
        right_panel.addWidget(self.question_display, 2)

        # 操作按钮
        self._create_action_buttons(right_panel)
        layout.addLayout(right_panel, 2)

    def _create_action_buttons(self, layout):
        btn_layout = QHBoxLayout()
        actions = [
            ('新建卡片', self._add_card, STYLES['secondary_color']),
            ('编辑卡片', self._edit_card, '#27ae60'),
            ('开始学习', self._start_study, STYLES['primary_color'])
        ]
        for text, handler, color in actions:
            btn = QPushButton(text)
            btn.clicked.connect(handler)
            btn.setStyleSheet(f"background: {color}; color: white; padding: 8px;")
            btn_layout.addWidget(btn)
        layout.addLayout(btn_layout)

    def _create_menu(self):
        menu = self.menuBar()
        help_menu = menu.addMenu('帮助')
        help_action = QAction('使用指南', self)
        help_action.triggered.connect(self._show_help)
        help_menu.addAction(help_action)

    def _setup_shortcuts(self):
        shortcuts = {
            Qt.Key_A: self._add_card,
            Qt.Key_E: self._edit_card,
            Qt.Key_S: self._start_study,
            Qt.Key_Delete: self._delete_card
        }
        for key, handler in shortcuts.items():
            QShortcut(key, self).activated.connect(handler)

    def _load_cards(self):
        self.card_list.clear()
        cursor = self.db.execute_query('''
            SELECT cards.id, question, GROUP_CONCAT(tags.name, ', ') 
            FROM cards
            LEFT JOIN card_tags ON cards.id = card_tags.card_id
            LEFT JOIN tags ON tags.id = card_tags.tag_id
            GROUP BY cards.id
            ORDER BY modified DESC
        ''')
        for card_id, question, tags in cursor.fetchall():
            item = QListWidgetItem(f"{question} [{tags or '无标签'}]")
            item.setData(Qt.UserRole, card_id)
            self.card_list.addItem(item)

    def _show_card_detail(self, item):
        card_id = item.data(Qt.UserRole)
        cursor = self.db.execute_query('''
            SELECT question, answer, proficiency, modified 
            FROM cards WHERE id = ?
        ''', (card_id,))
        result = cursor.fetchone()
        
        if result:
            question, answer, proficiency, modified = result
            self.question_display.setText(f'''
                <h2>{question}</h2>
                <hr>
                <p style="color:#666;">{answer}</p>
                <p style="margin-top:20px;">熟练度: {proficiency}%</p>
                <p>最后修改: {modified}</p>
            ''')

    def _add_card(self):
        dialog = CardEditor(self.db)
        if dialog.exec_() == QDialog.Accepted:
            self.data_updated.emit()
            self._load_cards()

    def _edit_card(self):
        if item := self.card_list.currentItem():
            card_id = item.data(Qt.UserRole)
            dialog = CardEditor(self.db, card_id)
            if dialog.exec_() == QDialog.Accepted:
                self._load_cards()

    def _delete_card(self):
        if item := self.card_list.currentItem():
            confirm = QMessageBox.question(self, '确认删除', '确定要删除该卡片吗？')
            if confirm == QMessageBox.Yes:
                card_id = item.data(Qt.UserRole)
                self.db.execute_query('DELETE FROM cards WHERE id = ?', (card_id,))
                self.db.commit()
                self._load_cards()

    def _start_study(self):
        tags = self._get_all_tags()
        if not tags:
            QMessageBox.warning(self, '提示', '请先创建标签')
            return
        
        tag, ok = QInputDialog.getItem(self, '选择标签', '请选择学习标签:', ['所有卡片'] + tags)
        if ok and tag:
            StudySession(self.db, tag if tag != '所有卡片' else None).exec_()

    def _get_all_tags(self):
        cursor = self.db.execute_query('SELECT name FROM tags')
        return [row[0] for row in cursor.fetchall()]

    def _show_help(self):
        QMessageBox.information(self, '帮助', '''
        快捷键指南：
        A - 新建卡片
        E - 编辑当前卡片
        S - 开始学习
        Delete - 删除当前卡片
        
        学习模式：
        空格键 - 显示/隐藏答案
        1/2/3 - 设置熟练度为20%/50%/100%
        ''')

class CardEditor(QDialog):
    def __init__(self, db, card_id=None):
        super().__init__()
        self.db = db
        self.card_id = card_id
        self._init_ui()
        self._load_data()

    def _init_ui(self):
        self.setWindowTitle('编辑卡片' if self.card_id else '新建卡片')
        self.setMinimumSize(600, 400)
        layout = QVBoxLayout()

        # 问题输入
        self.question_edit = QTextEdit()
        self.question_edit.setPlaceholderText('输入问题...')
        layout.addWidget(QLabel('问题:'))
        layout.addWidget(self.question_edit)

        # 答案输入
        self.answer_edit = QTextEdit()
        self.answer_edit.setPlaceholderText('输入答案...')
        layout.addWidget(QLabel('答案:'))
        layout.addWidget(self.answer_edit)

        # 标签管理
        self.tag_selector = TagManager(self.db)
        layout.addWidget(QLabel('标签:'))
        layout.addWidget(self.tag_selector)

        # 操作按钮
        btn_box = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Cancel)
        btn_box.accepted.connect(self._save_card)
        btn_box.rejected.connect(self.reject)
        layout.addWidget(btn_box)

        self.setLayout(layout)

    def _load_data(self):
        if self.card_id:
            cursor = self.db.execute_query('''
                SELECT question, answer, GROUP_CONCAT(tags.name)
                FROM cards
                LEFT JOIN card_tags ON cards.id = card_tags.card_id
                LEFT JOIN tags ON tags.id = card_tags.tag_id
                WHERE cards.id = ?
                GROUP BY cards.id
            ''', (self.card_id,))
            if result := cursor.fetchone():
                self.question_edit.setText(result[0])
                self.answer_edit.setText(result[1])
                if result[2]:
                    self.tag_selector.set_selected_tags(result[2].split(','))

    def _save_card(self):
        question = self.question_edit.toPlainText().strip()
        answer = self.answer_edit.toPlainText().strip()
        if not question or not answer:
            QMessageBox.warning(self, '警告', '问题和答案不能为空')
            return

        try:
            if self.card_id:
                self._update_card(question, answer)
            else:
                self._create_card(question, answer)
            self.accept()
        except Exception as e:
            QMessageBox.critical(self, '错误', f'保存失败: {str(e)}')

    def _create_card(self, question, answer):
        cursor = self.db.execute_query('''
            INSERT INTO cards (question, answer) VALUES (?, ?)
        ''', (question, answer))
        card_id = cursor.lastrowid
        self._update_tags(card_id)
        self.db.commit()

    def _update_card(self, question, answer):
        self.db.execute_query('''
            UPDATE cards SET question=?, answer=?, modified=CURRENT_TIMESTAMP 
            WHERE id=?
        ''', (question, answer, self.card_id))
        self._update_tags(self.card_id)
        self.db.commit()

    def _update_tags(self, card_id):
        selected_tags = self.tag_selector.get_selected_tags()
        
        # 清除旧标签
        self.db.execute_query('DELETE FROM card_tags WHERE card_id=?', (card_id,))
        
        # 插入新标签
        for tag_name in selected_tags:
            # 获取或创建标签ID
            cursor = self.db.execute_query('''
                INSERT OR IGNORE INTO tags (name) VALUES (?)
            ''', (tag_name,))
            tag_id = self.db.execute_query('SELECT id FROM tags WHERE name=?', 
                                          (tag_name,)).fetchone()[0]
            self.db.execute_query('''
                INSERT OR IGNORE INTO card_tags (card_id, tag_id) VALUES (?, ?)
            ''', (card_id, tag_id))

class TagManager(QWidget):
    def __init__(self, db):
        super().__init__()
        self.db = db
        self._init_ui()
        self._load_tags()

    def _init_ui(self):
        layout = QVBoxLayout()

        # 标签列表
        self.tag_list = QListWidget()
        self.tag_list.setSelectionMode(QListWidget.MultiSelection)
        layout.addWidget(self.tag_list)

        # 标签操作
        control_layout = QHBoxLayout()
        self.new_tag_input = QLineEdit()
        self.new_tag_input.setPlaceholderText('输入新标签')
        control_layout.addWidget(self.new_tag_input)

        self.add_btn = QPushButton('添加')
        self.add_btn.clicked.connect(self._add_tag)
        control_layout.addWidget(self.add_btn)

        self.remove_btn = QPushButton('删除')
        self.remove_btn.clicked.connect(self._remove_tags)
        control_layout.addWidget(self.remove_btn)

        layout.addLayout(control_layout)
        self.setLayout(layout)

    def _load_tags(self):
        self.tag_list.clear()
        cursor = self.db.execute_query('SELECT name FROM tags ORDER BY name')
        for (tag_name,) in cursor.fetchall():
            item = QListWidgetItem(tag_name)
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(Qt.Unchecked)
            self.tag_list.addItem(item)

    def set_selected_tags(self, tags):
        for i in range(self.tag_list.count()):
            item = self.tag_list.item(i)
            item.setCheckState(Qt.Checked if item.text() in tags else Qt.Unchecked)

    def get_selected_tags(self):
        return [self.tag_list.item(i).text() 
                for i in range(self.tag_list.count())
                if self.tag_list.item(i).checkState() == Qt.Checked]

    def _add_tag(self):
        tag_name = self.new_tag_input.text().strip()
        if tag_name:
            try:
                self.db.execute_query('INSERT OR IGNORE INTO tags (name) VALUES (?)', (tag_name,))
                self.db.commit()
                self._load_tags()
                self.new_tag_input.clear()
            except sqlite3.Error as e:
                QMessageBox.critical(self, '错误', f'添加失败: {str(e)}')

    def _remove_tags(self):
        selected = [item.text() for item in self.tag_list.selectedItems()]
        if selected:
            confirm = QMessageBox.question(self, '确认删除', f'确定删除{len(selected)}个标签吗？')
            if confirm == QMessageBox.Yes:
                try:
                    self.db.execute_query('DELETE FROM tags WHERE name IN (%s)' % 
                                        ','.join(['?']*len(selected)), selected)
                    self.db.commit()
                    self._load_tags()
                except sqlite3.Error as e:
                    QMessageBox.critical(self, '错误', f'删除失败: {str(e)}')

class StudySession(QDialog):
    def __init__(self, db, tag_filter=None):
        super().__init__()
        self.db = db
        self.tag_filter = tag_filter
        self.cards = self._load_cards()
        self.current_index = 0
        self._init_ui()
        self._setup_shortcuts()

    def _load_cards(self):
        query = '''
            SELECT id, question, answer, proficiency 
            FROM cards
            {}
            ORDER BY RANDOM()
        '''.format('WHERE EXISTS (SELECT 1 FROM card_tags JOIN tags ON tags.id = card_tags.tag_id WHERE tags.name = ? AND card_tags.card_id = cards.id)' 
                  if self.tag_filter else '')
        params = (self.tag_filter,) if self.tag_filter else ()
        cursor = self.db.execute_query(query, params)
        return cursor.fetchall()

    def _init_ui(self):
        self.setWindowTitle('学习模式')
        self.setMinimumSize(800, 500)
        layout = QVBoxLayout()

        # 显示区域
        self.question_label = QLabel()
        self.question_label.setAlignment(Qt.AlignCenter)
        self.question_label.setStyleSheet('font-size: 24px; margin: 20px;')
        layout.addWidget(self.question_label)

        self.answer_label = QLabel()
        self.answer_label.setAlignment(Qt.AlignCenter)
        self.answer_label.setStyleSheet('''
            font-size: 20px; color: #666; 
            background: #f8f9fa; 
            padding: 20px;
            border-radius: 10px;
            margin: 20px;
        ''')
        layout.addWidget(self.answer_label)
        self.answer_label.hide()

        # 控制按钮
        control_layout = QHBoxLayout()
        self.show_answer_btn = QPushButton('显示答案 (空格)')
        self.show_answer_btn.clicked.connect(lambda: self.answer_label.setVisible(True))
        control_layout.addWidget(self.show_answer_btn)

        self.next_btn = QPushButton('下一个 (→)')
        self.next_btn.clicked.connect(self._next_card)
        control_layout.addWidget(self.next_btn)

        layout.addLayout(control_layout)
        self.setLayout(layout)
        self._show_current_card()

    def _setup_shortcuts(self):
        self._add_shortcut(Qt.Key_Space, lambda: self.answer_label.setVisible(True))
        self._add_shortcut(Qt.Key_Right, self._next_card)
        self._add_shortcut(Qt.Key_1, lambda: self._set_proficiency(20))
        self._add_shortcut(Qt.Key_2, lambda: self._set_proficiency(50))
        self._add_shortcut(Qt.Key_3, lambda: self._set_proficiency(100))

    def _add_shortcut(self, key, handler):
        QShortcut(key, self).activated.connect(handler)

    def _show_current_card(self):
        if self.cards:
            card_id, question, answer, proficiency = self.cards[self.current_index]
            self.question_label.setText(question)
            self.answer_label.setText(answer)
            self.answer_label.hide()
        else:
            self.reject()

    def _next_card(self):
        self.current_index += 1
        if self.current_index < len(self.cards):
            self._show_current_card()
        else:
            QMessageBox.information(self, '完成', '本次学习已完成！')
            self.accept()

    def _set_proficiency(self, value):
        if self.cards:
            card_id = self.cards[self.current_index][0]
            self.db.execute_query('''
                UPDATE cards SET proficiency = ?, modified = CURRENT_TIMESTAMP 
                WHERE id = ?
            ''', (value, card_id))
            self.db.commit()
            self._next_card()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle('Fusion')
    window = MemoryApp()
    window.show()
    sys.exit(app.exec_())